package org.nalai.tools;

import com.esotericsoftware.kryo.Kryo;
import com.esotericsoftware.kryo.KryoException;
import com.esotericsoftware.kryo.io.Input;
import com.esotericsoftware.kryo.io.Output;

import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

public class KryoUtil {

    public static void toBinFile(String binFilePath, List<KryoPojo1> objList) throws Exception {
        Kryo kryo = new Kryo();

        Path storagePath = Paths.get(binFilePath);
        Output output = new Output(Files.newOutputStream(storagePath));

        for (KryoPojo1 obj : objList) {
            kryo.writeClassAndObject(output, obj);
        }

        output.flush();
        output.close();
    }

    public static List<KryoPojo1> fromBinFile(String binFilePath) throws Exception {

        Kryo kryo = new Kryo();

        Path storagePath = Paths.get(binFilePath);
        Input input = new Input(Files.newInputStream(storagePath));

        List<KryoPojo1> objList = new LinkedList<KryoPojo1>();

        try {

            while (input.available() > 0) {
                objList.add((KryoPojo1) kryo.readClassAndObject(input));
            }

            input.close();
        } catch (KryoException ignored) {
            ignored.printStackTrace();
        }

        return objList;
    }


    public static void main(String[] args) throws Exception {
//        long start = System.currentTimeMillis();
//        setSerializableObject();
//        System.out.println("Kryo Serializable writeObject time:" + (System.currentTimeMillis() - start) + " ms");
//        start = System.currentTimeMillis();
//        getSerializableObject();
//        System.out.println("Kryo Serializable readObject time:" + (System.currentTimeMillis() - start) + " ms");

        List<KryoPojo1> objList = new LinkedList<KryoPojo1>();

        for (int i = 101; i < 200; i++) {
            Map<String, Integer> map = new HashMap<String, Integer>(2);
            map.put("key1", i);
            map.put("key2", i);
            objList.add(new KryoPojo1("zhang" + i, i, map));
        }

        toBinFile("file2.bin", objList);

        List<KryoPojo1> objList2 = fromBinFile("file2.bin");
        for (KryoPojo1 simple : objList2) {
            System.out.println(simple.getAge() + "  " + simple.getName() + " " + simple.getMap().toString());
        }
    }

    private static void setSerializableObject() throws Exception {

        Kryo kryo = new Kryo();
//        kryo.setReferences(false);
//        kryo.setRegistrationRequired(false);
//        kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());
//        kryo.register(KryoPojo1.class);

        Path storagePath = Paths.get("file.bin");
        Output output = new Output(Files.newOutputStream(storagePath));
        for (int i = 101; i < 200; i++) {
            Map<String, Integer> map = new HashMap<String, Integer>(2);
            map.put("key1", i);
            map.put("key2", i);
//            kryo.writeObject(output, new KryoPojo1("zhang" + i, i));

            kryo.writeClassAndObject(output, new KryoPojo1("zhang" + i, i, map));
        }
        output.flush();
        output.close();
    }

    private static void getSerializableObject() throws Exception {

        Kryo kryo = new Kryo();
//        kryo.setReferences(false);
//        kryo.setRegistrationRequired(false);
//        kryo.setInstantiatorStrategy(new StdInstantiatorStrategy());

        Path storagePath = Paths.get("file.bin");
        Input input = new Input(Files.newInputStream(storagePath));

        KryoPojo1 simple;

        try {

            while (input.available() > 0) {
                simple = (KryoPojo1) kryo.readClassAndObject(input);
                System.out.println(simple.getAge() + "  " + simple.getName() + " " + simple.getMap().toString());
            }

//            while ((simple = (KryoPojo1) kryo.readClassAndObject(input)) != null) {
//                System.out.println(simple.getAge() + "  " + simple.getName() + " " + simple.getMap().toString());
//            }

            input.close();
        } catch (KryoException ignored) {
            ignored.printStackTrace();
        }
    }
}
